1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.nio.cs.ext;
27
28 import java.util.Collections;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.nio.charset.*;
34
35 final class CompoundTextSupport {
36
37 private static final class ControlSequence {
38
39 final int hash;
40 final byte[] escSequence;
41 final byte[] encoding;
42
43 ControlSequence(byte[] escSequence) {
44 this(escSequence, null);
45 }
46 ControlSequence(byte[] escSequence, byte[] encoding) {
47 if (escSequence == null) {
48 throw new NullPointerException();
49 }
50
51 this.escSequence = escSequence;
52 this.encoding = encoding;
53
54 int hash = 0;
55 int length = escSequence.length;
56
57 for (int i = 0; i < escSequence.length; i++) {
58 hash += (((int)escSequence[i]) & 0xff) << (i % 4);
59 }
60 if (encoding != null) {
61 for (int i = 0; i < encoding.length; i++) {
62 hash += (((int)encoding[i]) & 0xff) << (i % 4);
63 }
64 length += 2 + encoding.length + 1 ;
65 }
66
67 this.hash = hash;
68
69 if (MAX_CONTROL_SEQUENCE_LEN < length) {
70 MAX_CONTROL_SEQUENCE_LEN = length;
71 }
72 }
73
74 public boolean equals(Object obj) {
75 if (this == obj) {
76 return true;
77 }
78 if (!(obj instanceof ControlSequence)) {
79 return false;
80 }
81 ControlSequence rhs = (ControlSequence)obj;
82 if (escSequence != rhs.escSequence) {
83 if (escSequence.length != rhs.escSequence.length) {
84 return false;
85 }
86 for (int i = 0; i < escSequence.length; i++) {
87 if (escSequence[i] != rhs.escSequence[i]) {
88 return false;
89 }
90 }
91 }
92 if (encoding != rhs.encoding) {
93 if (encoding == null || rhs.encoding == null ||
94 encoding.length != rhs.encoding.length)
95 {
96 return false;
97 }
98 for (int i = 0; i < encoding.length; i++) {
99 if (encoding[i] != rhs.encoding[i]) {
100 return false;
101 }
102 }
103 }
104 return true;
105 }
106
107 public int hashCode() {
108 return hash;
109 }
110
111 ControlSequence concatenate(ControlSequence rhs) {
112 if (encoding != null) {
113 throw new IllegalArgumentException
114 ("cannot concatenate to a non-standard charset escape " +
115 "sequence");
116 }
117
118 int len = escSequence.length + rhs.escSequence.length;
119 byte[] newEscSequence = new byte[len];
120 System.arraycopy(escSequence, 0, newEscSequence, 0,
121 escSequence.length);
122 System.arraycopy(rhs.escSequence, 0, newEscSequence,
123 escSequence.length, rhs.escSequence.length);
124 return new ControlSequence(newEscSequence, rhs.encoding);
125 }
126 }
127
128 static int MAX_CONTROL_SEQUENCE_LEN;
129
130
131
132
133 private static final Map<ControlSequence, String> sequenceToEncodingMap;
134
135
136
137
138
139 private static final Map<ControlSequence, Boolean> highBitsMap;
140
141
142
143
144
145
146
147 private static final Map<String, ControlSequence> encodingToSequenceMap;
148
149
150
151
152 private static final List<String> encodings;
153
154 static {
155 HashMap<ControlSequence, String> tSequenceToEncodingMap =
156 new HashMap<>(33, 1.0f);
157 HashMap<ControlSequence, Boolean> tHighBitsMap =
158 new HashMap<>(31, 1.0f);
159 HashMap<String, ControlSequence> tEncodingToSequenceMap =
160 new HashMap<>(21, 1.0f);
161 ArrayList<String> tEncodings = new ArrayList<>(21);
162
163 if (!(isEncodingSupported("US-ASCII") &&
164 isEncodingSupported("ISO-8859-1")))
165 {
166 throw new ExceptionInInitializerError
167 ("US-ASCII and ISO-8859-1 unsupported");
168 }
169
170 ControlSequence leftAscii =
171 new ControlSequence(new byte[] { 0x1B, 0x28, 0x42 });
172 tSequenceToEncodingMap.put(leftAscii, "US-ASCII");
173 tHighBitsMap.put(leftAscii, Boolean.FALSE);
174
175 {
176 ControlSequence rightAscii =
177 new ControlSequence(new byte[] { 0x1B, 0x29, 0x42 });
178 tSequenceToEncodingMap.put(rightAscii, "US-ASCII");
179 tHighBitsMap.put(rightAscii, Boolean.FALSE);
180 }
181
182 {
183 ControlSequence rightHalf =
184 new ControlSequence(new byte[] { 0x1B, 0x2D, 0x41 });
185 tSequenceToEncodingMap.put(rightHalf, "ISO-8859-1");
186 tHighBitsMap.put(rightHalf, Boolean.TRUE);
187
188 ControlSequence fullSet = leftAscii.concatenate(rightHalf);
189 tEncodingToSequenceMap.put("ISO-8859-1", fullSet);
190 tEncodings.add("ISO-8859-1");
191 }
192 if (isEncodingSupported("ISO-8859-2")) {
193 ControlSequence rightHalf =
194 new ControlSequence(new byte[] { 0x1B, 0x2D, 0x42 });
195 tSequenceToEncodingMap.put(rightHalf, "ISO-8859-2");
196 tHighBitsMap.put(rightHalf, Boolean.TRUE);
197
198 ControlSequence fullSet = leftAscii.concatenate(rightHalf);
199 tEncodingToSequenceMap.put("ISO-8859-2", fullSet);
200 tEncodings.add("ISO-8859-2");
201 }
202 if (isEncodingSupported("ISO-8859-3")) {
203 ControlSequence rightHalf =
204 new ControlSequence(new byte[] { 0x1B, 0x2D, 0x43 });
205 tSequenceToEncodingMap.put(rightHalf, "ISO-8859-3");
206 tHighBitsMap.put(rightHalf, Boolean.TRUE);
207
208 ControlSequence fullSet = leftAscii.concatenate(rightHalf);
209 tEncodingToSequenceMap.put("ISO-8859-3", fullSet);
210 tEncodings.add("ISO-8859-3");
211 }
212 if (isEncodingSupported("ISO-8859-4")) {
213 ControlSequence rightHalf =
214 new ControlSequence(new byte[] { 0x1B, 0x2D, 0x44 });
215 tSequenceToEncodingMap.put(rightHalf, "ISO-8859-4");
216 tHighBitsMap.put(rightHalf, Boolean.TRUE);
217
218 ControlSequence fullSet = leftAscii.concatenate(rightHalf);
219 tEncodingToSequenceMap.put("ISO-8859-4", fullSet);
220 tEncodings.add("ISO-8859-4");
221 }
222 if (isEncodingSupported("ISO-8859-5")) {
223 ControlSequence rightHalf =
224 new ControlSequence(new byte[] { 0x1B, 0x2D, 0x4C });
225 tSequenceToEncodingMap.put(rightHalf, "ISO-8859-5");
226 tHighBitsMap.put(rightHalf, Boolean.TRUE);
227
228 ControlSequence fullSet = leftAscii.concatenate(rightHalf);
229 tEncodingToSequenceMap.put("ISO-8859-5", fullSet);
230 tEncodings.add("ISO-8859-5");
231 }
232 if (isEncodingSupported("ISO-8859-6")) {
233 ControlSequence rightHalf =
234 new ControlSequence(new byte[] { 0x1B, 0x2D, 0x47 });
235 tSequenceToEncodingMap.put(rightHalf, "ISO-8859-6");
236 tHighBitsMap.put(rightHalf, Boolean.TRUE);
237
238 ControlSequence fullSet = leftAscii.concatenate(rightHalf);
239 tEncodingToSequenceMap.put("ISO-8859-6", fullSet);
240 tEncodings.add("ISO-8859-6");
241 }
242 if (isEncodingSupported("ISO-8859-7")) {
243 ControlSequence rightHalf =
244 new ControlSequence(new byte[] { 0x1B, 0x2D, 0x46 });
245 tSequenceToEncodingMap.put(rightHalf, "ISO-8859-7");
246 tHighBitsMap.put(rightHalf, Boolean.TRUE);
247
248 ControlSequence fullSet = leftAscii.concatenate(rightHalf);
249 tEncodingToSequenceMap.put("ISO-8859-7", fullSet);
250 tEncodings.add("ISO-8859-7");
251 }
252 if (isEncodingSupported("ISO-8859-8")) {
253 ControlSequence rightHalf =
254 new ControlSequence(new byte[] { 0x1B, 0x2D, 0x48 });
255 tSequenceToEncodingMap.put(rightHalf, "ISO-8859-8");
256 tHighBitsMap.put(rightHalf, Boolean.TRUE);
257
258 ControlSequence fullSet = leftAscii.concatenate(rightHalf);
259 tEncodingToSequenceMap.put("ISO-8859-8", fullSet);
260 tEncodings.add("ISO-8859-8");
261 }
262 if (isEncodingSupported("ISO-8859-9")) {
263 ControlSequence rightHalf =
264 new ControlSequence(new byte[] { 0x1B, 0x2D, 0x4D });
265 tSequenceToEncodingMap.put(rightHalf, "ISO-8859-9");
266 tHighBitsMap.put(rightHalf, Boolean.TRUE);
267
268 ControlSequence fullSet = leftAscii.concatenate(rightHalf);
269 tEncodingToSequenceMap.put("ISO-8859-9", fullSet);
270 tEncodings.add("ISO-8859-9");
271 }
272 if (isEncodingSupported("JIS_X0201")) {
273 ControlSequence glLeft =
274 new ControlSequence(new byte[] { 0x1B, 0x28, 0x4A });
275 ControlSequence glRight =
276 new ControlSequence(new byte[] { 0x1B, 0x28, 0x49 });
277 ControlSequence grLeft =
278 new ControlSequence(new byte[] { 0x1B, 0x29, 0x4A });
279 ControlSequence grRight =
280 new ControlSequence(new byte[] { 0x1B, 0x29, 0x49 });
281 tSequenceToEncodingMap.put(glLeft, "JIS_X0201");
282 tSequenceToEncodingMap.put(glRight, "JIS_X0201");
283 tSequenceToEncodingMap.put(grLeft, "JIS_X0201");
284 tSequenceToEncodingMap.put(grRight, "JIS_X0201");
285 tHighBitsMap.put(glLeft, Boolean.FALSE);
286 tHighBitsMap.put(glRight, Boolean.TRUE);
287 tHighBitsMap.put(grLeft, Boolean.FALSE);
288 tHighBitsMap.put(grRight, Boolean.TRUE);
289
290 ControlSequence fullSet = glLeft.concatenate(grRight);
291 tEncodingToSequenceMap.put("JIS_X0201", fullSet);
292 tEncodings.add("JIS_X0201");
293 }
294 if (isEncodingSupported("X11GB2312")) {
295 ControlSequence leftHalf =
296 new ControlSequence(new byte[] { 0x1B, 0x24, 0x28, 0x41 });
297 ControlSequence rightHalf =
298 new ControlSequence(new byte[] { 0x1B, 0x24, 0x29, 0x41 });
299 tSequenceToEncodingMap.put(leftHalf, "X11GB2312");
300 tSequenceToEncodingMap.put(rightHalf, "X11GB2312");
301 tHighBitsMap.put(leftHalf, Boolean.FALSE);
302 tHighBitsMap.put(rightHalf, Boolean.FALSE);
303
304 tEncodingToSequenceMap.put("X11GB2312", leftHalf);
305 tEncodings.add("X11GB2312");
306 }
307 if (isEncodingSupported("x-JIS0208")) {
308 ControlSequence leftHalf =
309 new ControlSequence(new byte[] { 0x1B, 0x24, 0x28, 0x42 });
310 ControlSequence rightHalf =
311 new ControlSequence(new byte[] { 0x1B, 0x24, 0x29, 0x42 });
312 tSequenceToEncodingMap.put(leftHalf, "x-JIS0208");
313 tSequenceToEncodingMap.put(rightHalf, "x-JIS0208");
314 tHighBitsMap.put(leftHalf, Boolean.FALSE);
315 tHighBitsMap.put(rightHalf, Boolean.FALSE);
316
317 tEncodingToSequenceMap.put("x-JIS0208", leftHalf);
318 tEncodings.add("x-JIS0208");
319 }
320 if (isEncodingSupported("X11KSC5601")) {
321 ControlSequence leftHalf =
322 new ControlSequence(new byte[] { 0x1B, 0x24, 0x28, 0x43 });
323 ControlSequence rightHalf =
324 new ControlSequence(new byte[] { 0x1B, 0x24, 0x29, 0x43 });
325 tSequenceToEncodingMap.put(leftHalf, "X11KSC5601");
326 tSequenceToEncodingMap.put(rightHalf, "X11KSC5601");
327 tHighBitsMap.put(leftHalf, Boolean.FALSE);
328 tHighBitsMap.put(rightHalf, Boolean.FALSE);
329
330 tEncodingToSequenceMap.put("X11KSC5601", leftHalf);
331 tEncodings.add("X11KSC5601");
332 }
333
334
335
336
337 if (isEncodingSupported("ISO-8859-15")) {
338 ControlSequence rightHalf =
339 new ControlSequence(new byte[] { 0x1B, 0x2D, 0x62 });
340 tSequenceToEncodingMap.put(rightHalf, "ISO-8859-15");
341 tHighBitsMap.put(rightHalf, Boolean.TRUE);
342
343 ControlSequence fullSet = leftAscii.concatenate(rightHalf);
344 tEncodingToSequenceMap.put("ISO-8859-15", fullSet);
345 tEncodings.add("ISO-8859-15");
346 }
347
348 if (isEncodingSupported("TIS-620")) {
349 ControlSequence rightHalf =
350 new ControlSequence(new byte[] { 0x1B, 0x2D, 0x54 });
351 tSequenceToEncodingMap.put(rightHalf, "TIS-620");
352 tHighBitsMap.put(rightHalf, Boolean.TRUE);
353
354 ControlSequence fullSet = leftAscii.concatenate(rightHalf);
355 tEncodingToSequenceMap.put("TIS-620", fullSet);
356 tEncodings.add("TIS-620");
357 }
358 if (isEncodingSupported("JIS_X0212-1990")) {
359 ControlSequence leftHalf =
360 new ControlSequence(new byte[] { 0x1B, 0x24, 0x28, 0x44 });
361 ControlSequence rightHalf =
362 new ControlSequence(new byte[] { 0x1B, 0x24, 0x29, 0x44 });
363 tSequenceToEncodingMap.put(leftHalf, "JIS_X0212-1990");
364 tSequenceToEncodingMap.put(rightHalf, "JIS_X0212-1990");
365 tHighBitsMap.put(leftHalf, Boolean.FALSE);
366 tHighBitsMap.put(rightHalf, Boolean.FALSE);
367
368 tEncodingToSequenceMap.put("JIS_X0212-1990", leftHalf);
369 tEncodings.add("JIS_X0212-1990");
370 }
371 if (isEncodingSupported("X11CNS11643P1")) {
372 ControlSequence leftHalf =
373 new ControlSequence(new byte[] { 0x1B, 0x24, 0x28, 0x47 });
374 ControlSequence rightHalf =
375 new ControlSequence(new byte[] { 0x1B, 0x24, 0x29, 0x47 });
376 tSequenceToEncodingMap.put(leftHalf, "X11CNS11643P1");
377 tSequenceToEncodingMap.put(rightHalf, "X11CNS11643P1");
378 tHighBitsMap.put(leftHalf, Boolean.FALSE);
379 tHighBitsMap.put(rightHalf, Boolean.FALSE);
380
381 tEncodingToSequenceMap.put("X11CNS11643P1", leftHalf);
382 tEncodings.add("X11CNS11643P1");
383 }
384 if (isEncodingSupported("X11CNS11643P2")) {
385 ControlSequence leftHalf =
386 new ControlSequence(new byte[] { 0x1B, 0x24, 0x28, 0x48 });
387 ControlSequence rightHalf =
388 new ControlSequence(new byte[] { 0x1B, 0x24, 0x29, 0x48 });
389 tSequenceToEncodingMap.put(leftHalf, "X11CNS11643P2");
390 tSequenceToEncodingMap.put(rightHalf, "X11CNS11643P2");
391 tHighBitsMap.put(leftHalf, Boolean.FALSE);
392 tHighBitsMap.put(rightHalf, Boolean.FALSE);
393
394 tEncodingToSequenceMap.put("X11CNS11643P2", leftHalf);
395 tEncodings.add("X11CNS11643P2");
396 }
397 if (isEncodingSupported("X11CNS11643P3")) {
398 ControlSequence leftHalf =
399 new ControlSequence(new byte[] { 0x1B, 0x24, 0x28, 0x49 });
400 ControlSequence rightHalf =
401 new ControlSequence(new byte[] { 0x1B, 0x24, 0x29, 0x49 });
402 tSequenceToEncodingMap.put(leftHalf, "X11CNS11643P3");
403 tSequenceToEncodingMap.put(rightHalf, "X11CNS11643P3");
404 tHighBitsMap.put(leftHalf, Boolean.FALSE);
405 tHighBitsMap.put(rightHalf, Boolean.FALSE);
406
407 tEncodingToSequenceMap.put("X11CNS11643P3", leftHalf);
408 tEncodings.add("X11CNS11643P3");
409 }
410
411 if (isEncodingSupported("x-Johab")) {
412
413
414
415
416 ControlSequence johab = new ControlSequence(
417 new byte[] { 0x1b, 0x25, 0x2f, 0x32 },
418 new byte[] { 0x53, 0x55, 0x4e, 0x2d, 0x4b, 0x53, 0x43, 0x35,
419 0x36, 0x30, 0x31, 0x2e, 0x31, 0x39, 0x39, 0x32,
420 0x2d, 0x33 });
421 tSequenceToEncodingMap.put(johab, "x-Johab");
422 tEncodingToSequenceMap.put("x-Johab", johab);
423 tEncodings.add("x-Johab");
424 }
425
426 if (isEncodingSupported("Big5")) {
427
428
429
430
431 ControlSequence big5 = new ControlSequence(
432 new byte[] { 0x1b, 0x25, 0x2f, 0x32 },
433 new byte[] { 0x53, 0x55, 0x4e, 0x2d, 0x42, 0x49, 0x47, 0x35,
434 0x2d, 0x31 });
435 tSequenceToEncodingMap.put(big5, "Big5");
436 tEncodingToSequenceMap.put("Big5", big5);
437 tEncodings.add("Big5");
438 }
439
440 sequenceToEncodingMap =
441 Collections.unmodifiableMap(tSequenceToEncodingMap);
442 highBitsMap = Collections.unmodifiableMap(tHighBitsMap);
443 encodingToSequenceMap =
444 Collections.unmodifiableMap(tEncodingToSequenceMap);
445 encodings = Collections.unmodifiableList(tEncodings);
446 }
447
448 private static boolean isEncodingSupported(String encoding) {
449 try {
450 if (Charset.isSupported(encoding))
451 return true;
452 } catch (IllegalArgumentException x) { }
453 return (getDecoder(encoding) != null &&
454 getEncoder(encoding) != null);
455 }
456
457
458
459 static CharsetDecoder getStandardDecoder(byte[] escSequence) {
460 return getNonStandardDecoder(escSequence, null);
461 }
462 static boolean getHighBit(byte[] escSequence) {
463 Boolean bool = highBitsMap.get(new ControlSequence(escSequence));
464 return (bool == Boolean.TRUE);
465 }
466 static CharsetDecoder getNonStandardDecoder(byte[] escSequence,
467 byte[] encoding) {
468 return getDecoder(sequenceToEncodingMap.get
469 (new ControlSequence(escSequence, encoding)));
470 }
471 static CharsetDecoder getDecoder(String enc) {
472 if (enc == null) {
473 return null;
474 }
475 Charset cs = null;
476 try {
477 cs = Charset.forName(enc);
478 } catch (IllegalArgumentException e) {
479 Class<?> cls;
480 try {
481 cls = Class.forName("sun.awt.motif." + enc);
482 } catch (ClassNotFoundException ee) {
483 return null;
484 }
485 try {
486 cs = (Charset)cls.newInstance();
487 } catch (InstantiationException ee) {
488 return null;
489 } catch (IllegalAccessException ee) {
490 return null;
491 }
492 }
493 try {
494 return cs.newDecoder();
495 } catch (UnsupportedOperationException e) {}
496 return null;
497 }
498
499
500
501 static byte[] getEscapeSequence(String encoding) {
502 ControlSequence seq = encodingToSequenceMap.get(encoding);
503 if (seq != null) {
504 return seq.escSequence;
505 }
506 return null;
507 }
508 static byte[] getEncoding(String encoding) {
509 ControlSequence seq = encodingToSequenceMap.get(encoding);
510 if (seq != null) {
511 return seq.encoding;
512 }
513 return null;
514 }
515 static List<String> getEncodings() {
516 return encodings;
517 }
518 static CharsetEncoder getEncoder(String enc) {
519 if (enc == null) {
520 return null;
521 }
522 Charset cs = null;
523 try {
524 cs = Charset.forName(enc);
525 } catch (IllegalArgumentException e) {
526 Class<?> cls;
527 try {
528 cls = Class.forName("sun.awt.motif." + enc);
529 } catch (ClassNotFoundException ee) {
530 return null;
531 }
532 try {
533 cs = (Charset)cls.newInstance();
534 } catch (InstantiationException ee) {
535 return null;
536 } catch (IllegalAccessException ee) {
537 return null;
538 }
539 }
540 try {
541 return cs.newEncoder();
542 } catch (Throwable e) {}
543 return null;
544 }
545
546
547 private CompoundTextSupport() {}
548 }